import { ElLoading } from 'element-plus'
import * as Cesium from "cesium";
import GlobeRotate from './globeRotate'
import CesiumNavigation from "cesium-navigation-es6";
import ImageryProvider from "./imageryProvider";
import CesiumLocal from './cesiumLocal';
import AMapGeocoderService from './aMapGeocoderService';
import MeasureTools from './measureTools';
import MarkTools from './markTools';
import { MapImageryProvider } from './coordTransform';


class CesiumUtils {
    constructor(documentId = "cesiumContainer") {
        this.documentId = documentId
        this.selectedEntity = null
        this.position = {}
        this.flag = false
        this.isBehind = false
        this.pointHeight = 350
        this.measureTools = null;
    }

    getDefaultOptions() {
        return {
            homeButton: true,
            geocoder: true,
            sceneModePicker: true,
            baseLayerPicker: true,
            startGlobeRotate: false,
            openDebug: false,
            navigation: true,
            keyboard: false,
            chinaCamera: true,
            defaultImagery: 0,
            minimumZoom: 500,
        };
    }

    init(options) {

        // 合并默认选项和传入的选项  
        const mergedOptions = { ...this.getDefaultOptions(), ...options };

        // 加载动画
        this.loading = ElLoading.service({
            lock: true,
            text: 'Loading',
            background: 'rgba(0, 0, 0, 0.7)',
        })

        // 初始化地球
        try {
            this.providerViewModels = new ImageryProvider().providerViewModels
            Cesium.Ion.defaultAccessToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI5NGY3MDM5Yy02MDVjLTRkOWEtOWI5Zi02NDlhYTFiMzNjOTciLCJpZCI6MjA5Mjc1LCJpYXQiOjE3MzYxNzU4MTZ9.UWsm8A4Jlob9qENDIXRkPDt0o8z9ttIxPRJfbno60ho";

            var worldTerrain = Cesium.createWorldTerrain({
                requestWaterMask: true,
                requestVertexNormals: true
            });

            this.viewer = new Cesium.Viewer(this.documentId, {
                //地形图层TerrainProvider
                terrainProvider: worldTerrain,
                // 图层控件显隐控制
                infoBox: false, //隐藏信息框
                timeline: false, //隐藏时间轴
                animation: false, //隐藏动画控制器
                geocoder: mergedOptions.geocoder ? new AMapGeocoderService({ key: '4517eab7fa15718d4a8bb0cc3739a951' }) : false, //通过高德POI查询，需要key
                homeButton: mergedOptions.homeButton, //隐藏Home按钮
                imageryProviderViewModels: this.providerViewModels, //自定义扩展底图
                selectedImageryProviderViewModel: this.providerViewModels[mergedOptions.defaultImagery], // 默认选中第一个
                // terrainProviderViewModels: [], // 设置地形
                sceneModePicker: mergedOptions.sceneModePicker, //场景模式，切换2D、3D 和 Columbus View (CV) 模式
                baseLayerPicker: mergedOptions.baseLayerPicker, //隐藏图层选择控制器
                navigationHelpButton: false, //隐藏帮助按钮
                fullscreenButton: false, //隐藏全屏按钮
                // requestRenderMode: true, // 显示渲染帧，参考：https://cesium.com/blog/2018/01/24/cesium-scene-rendering-performance/
                // maximumRenderTimeChange: Infinity // 如果场景中没有随时间变化的元素，可以设置为一个较大的值
            });
            // 汉化
            this._local = new CesiumLocal(this.viewer)
            this.optionSet(mergedOptions);

            // 叠加矢量图（腾讯地图纠偏）
            const custom = new MapImageryProvider({
                url: 'https://rt3.map.gtimg.com/tile?z={z}&x={x}&y={reverseY}&styleid=2&version=297',
                crs: "WGS84"
            });

            this.viewer.imageryLayers.addImageryProvider(custom);


        } catch (exception) {
            const message = Cesium.formatError(exception);
            console.error(message);
        } finally {
            this.loading.close()
        }
        return this.viewer;
    }

    optionSet(mergedOptions) {
        // 显示fps
        // this.viewer.scene.debugShowFramesPerSecond = true;
        // 启用照明
        this.viewer.scene.globe.enableLighting = false;
        //去掉二三维切换动画效果
        // this.viewer.sceneModePicker.viewModel.duration = 0.0;
        // 取消版权信息
        this.viewer._cesiumWidget._creditContainer.style.display = "none";
        // 最小缩放距离
        this.viewer.scene.screenSpaceCameraController.minimumZoomDistance = mergedOptions.minimumZoom;
        if (mergedOptions.navigation) this.navigation();
        if (mergedOptions.chinaCamera) this.chinaCamera();
        if (mergedOptions.keyboard) this.keyboardMonitor();
        if (mergedOptions.openDebug) this.openDebug();
        this.startGlobeRotate(mergedOptions.startGlobeRotate);
        this.cameraChanged();
        this.saveSceneMode();
        this.switchSceneMode();
        // 保存默认数值
        this.resolutionScale = this.viewer.resolutionScale;
        this.fxaaEnabled(true);
    }


    /**
     * 开启cesium调试
     */
    openDebug() {
        if (this.viewer.debug) {
            const scene = this.viewer.scene;
            const context = scene.context;
            // 验证着色器程序
            context.validateShaderProgram = true;
            // 验证帧缓冲区
            context.validateFramebuffer = true;
            // 日志着色器编译
            context.logShaderCompilation = true;
            // 抛出 WebGL 错误
            context.throwOnWebGLError = true;
        }
        window.Cesium = Cesium;
        window.viewer = this.viewer;
    }

    /**
     * 设置中国地图视角
     */
    chinaCamera() {
        // 设置视图范围为中国大陆大致范围
        const chinaRectangle = Cesium.Rectangle.fromDegrees(
            73.0, // 西经（实际应为东经，但Cesium使用负数表示西经）  
            18.0, // 北纬  
            135.0, // 东经  
            54.0  // 北纬
        )

        // 视角初始值
        this.viewer.camera.setView({
            destination: chinaRectangle
        })

        if (this.viewer.homeButton) {
            // 修改homeButton的默认返回位置
            this.viewer.homeButton.viewModel.command.beforeExecute.addEventListener(e => {
                e.cancel = true
                this.viewer.camera.flyTo({
                    destination: chinaRectangle
                })
            })
        }

    }

    /**
     * 设置地图导航控件
     */
    navigation() {
        const options = {};
        // 用于在使用重置导航重置地图视图时设置默认视图控制。接受的值是Cesium.Cartographic 和Cesium.Rectangle.
        // options.defaultResetView = Cesium.Cartographic.fromDegrees(110, 30, 2000000);
        options.defaultResetView = Cesium.Rectangle.fromDegrees(
            73.0, // 西经（实际应为东经，但Cesium使用负数表示西经）  
            18.0, // 北纬  
            135.0, // 东经  
            54.0  // 北纬
        );
        // 用于启用或禁用罗盘。true是启用罗盘，false是禁用罗盘。默认值为true。如果将选项设置为false，则罗盘将不会添加到地图中。
        options.enableCompass = true;
        // 用于启用或禁用缩放控件。true是启用，false是禁用。默认值为true。如果将选项设置为false，则缩放控件 将不会添加到地图中。
        options.enableZoomControls = true;
        // 用于启用或禁用距离图例。true是启用，false是禁用。默认值为true。如果将选项设置为false，距离图例将不会添加到地图中。
        options.enableDistanceLegend = true;
        // 用于启用或禁用指南针外环。true是启用，false是禁用。默认值为true。如果将选项设置为false，则该环将可见但无效。
        options.enableCompassOuterRing = true;
        new CesiumNavigation(this.viewer, options);

    }

    /**
     * 保存当前相机视角
     * 重入页面，加载并恢复之前保存的相机状态
     */
    cameraChanged() {
        const camera = this.viewer.camera;
        let timeout;
        // 相机视角变化监听
        camera.changed.addEventListener(function () {
            window.clearTimeout(timeout);
            // 1秒后执行
            timeout = window.setTimeout(saveCamera, 1000);
        });
        // 保存当前相机视角
        function saveCamera() {
            const { heading, pitch, roll } = camera;
            const { x, y, z } = camera.position;
            const cameraInfo = { x, y, z, heading, pitch, roll };
            localStorage.setItem("cameraInfo", JSON.stringify(cameraInfo));
        }
    }

    /**
     * 恢复相机视角
     */
    cameraSetView() {
        // 设置相机位置
        const cameraInfo = localStorage.getItem("cameraInfo");
        const JSONInfo = JSON.parse(cameraInfo);
        if (JSONInfo) {
            const { x, y, z, heading, pitch, roll } = JSONInfo;

            this.viewer.camera.setView({
                destination: { x, y, z },
                orientation: {
                    heading,
                    pitch,
                    roll,
                },
            });
        }
    }

    /**
     * 监听场景模式变化，保存当前场景模式
     */
    saveSceneMode() {
        // 监听场景模式变化
        this.viewer.scene.morphComplete.addEventListener(() => {
            localStorage.setItem("sceneMode", this.viewer.scene.mode);
        });
    }

    /**
     * 切换场景模式
     */
    switchSceneMode() {
        const sceneMode = localStorage.getItem("sceneMode");
        if (sceneMode) {
            this.viewer.scene.mode = Number(sceneMode);
        }
    }

    /**
     * 抗锯齿
     * @param {*} isFxaa 
     */
    fxaaEnabled(isFxaa) {
        if (Cesium.FeatureDetection.supportsImageRenderingPixelated()) {
            if (isFxaa) {
                this.viewer.resolutionScale = window.devicePixelRatio;
            } else {
                this.viewer.resolutionScale = this.resolutionScale;
            }
        }
        this.viewer.scene.fxaa = isFxaa;
        this.viewer.scene.postProcessStages.fxaa.enabled = isFxaa;
        this.viewer.scene.msaaSamples = 8;
        this.viewer.scene.highDynamicRange = true;
    }

    /**
     * 键盘监听，控制相机移动
     */
    keyboardMonitor1() {
        document.addEventListener("keydown", (e) => {
            const viewer = this.viewer;
            // 获取相机离地面的高度
            const height = viewer.camera.positionCartographic.height;
            const moveRate = height / 50;
            const radian = 0.5;

            if (e.key == "w") {
                // 设置相机向前移动
                viewer.camera.moveForward(moveRate);
            } else if (e.key == "s") {
                // 设置相机向后移动
                viewer.camera.moveBackward(moveRate);
            } else if (e.key == "a") {
                // 设置相机向左移动
                viewer.camera.moveLeft(moveRate);
            } else if (e.key == "d") {
                // 设置相机向右移动
                viewer.camera.moveRight(moveRate);
            } else if (e.key == "q") {
                // 设置相机向左旋转相机
                viewer.camera.lookLeft(Cesium.Math.toRadians(radian));
            } else if (e.key == "e") {
                // 设置相机向右旋转相机
                viewer.camera.lookRight(Cesium.Math.toRadians(radian));
            } else if (e.key == "r") {
                // 设置相机向上旋转相机
                viewer.camera.lookUp(Cesium.Math.toRadians(radian));
            } else if (e.key == "f") {
                // 设置相机向下旋转相机
                viewer.camera.lookDown(Cesium.Math.toRadians(radian));
            } else if (e.key == "g") {
                // 向左逆时针翻滚
                viewer.camera.twistLeft(Cesium.Math.toRadians(radian));
            } else if (e.key == "h") {
                // 向右顺时针翻滚
                viewer.camera.twistRight(Cesium.Math.toRadians(radian));
            }
        });
    }


    /**
     * 键盘监听，控制相机移动
     */
    keyboardMonitor() {
        const viewer = this.viewer;
        let scene = viewer.scene;
        let canvas = viewer.canvas;
        canvas.setAttribute('tabindex', '0'); // needed to put focus on the canvas
        canvas.onclick = function () {
            canvas.focus();
        };
        let ellipsoid = scene.globe.ellipsoid;

        let startMousePosition;
        let mousePosition;

        let flags = {
            looking: false,
            moveForward: false,
            moveBackward: false,
            moveUp: false,
            moveDown: false,
            moveLeft: false,
            moveRight: false
        };

        function getFlagForKeyCode(keyCode) {
            switch (keyCode) {
                case 'w':
                    return 'moveUp';
                case 's':
                    return 'moveDown';
                case 'q':
                    return 'moveForward';
                case 'e':
                    return 'moveBackward';
                case 'd':
                    return 'moveRight';
                case 'a':
                    return 'moveLeft';
                default:
                    return undefined;
            }
        }

        document.addEventListener('keydown', function (e) {
            let flagName = getFlagForKeyCode(e.key.toLowerCase());
            if (typeof flagName !== 'undefined') {
                flags[flagName] = true;
            }
        }, false);

        document.addEventListener('keyup', function (e) {
            let flagName = getFlagForKeyCode(e.key.toLowerCase());
            if (typeof flagName !== 'undefined') {
                flags[flagName] = false;
            }
        }, false);

        viewer.clock.onTick.addEventListener(function (clock) {
            let camera = viewer.camera;
            if (flags.looking) {
                let width = canvas.clientWidth;
                let height = canvas.clientHeight;

                // Coordinate (0.0, 0.0) will be where the mouse was clicked.
                let x = (mousePosition.x - startMousePosition.x) / width;
                let y = -(mousePosition.y - startMousePosition.y) / height;

                let lookFactor = 0.05;
                camera.lookRight(x * lookFactor);
                camera.lookUp(y * lookFactor);
            }

            // Change movement speed based on the distance of the camera to the surface of the ellipsoid.
            let cameraHeight = ellipsoid.cartesianToCartographic(camera.position).height;
            let moveRate = cameraHeight / 100.0;

            if (flags.moveForward) {
                camera.moveForward(moveRate);
            }
            if (flags.moveBackward) {
                camera.moveBackward(moveRate);
            }
            if (flags.moveUp) {
                camera.moveUp(moveRate);
            }
            if (flags.moveDown) {
                camera.moveDown(moveRate);
            }
            if (flags.moveLeft) {
                camera.moveLeft(moveRate);
            }
            if (flags.moveRight) {
                camera.moveRight(moveRate);
            }
        });
    }

    /**
     * 地球旋转
     * @param {*} isStart 
     */
    startGlobeRotate(isStart) {
        const rotate = new GlobeRotate(this.viewer)
        if (isStart) {
            rotate.start()
        } else {
            rotate.stop()
        }
    }

    /**
     * 添加3DTile
     * @param {*} url 
     * @returns 
     */
    add3DTile(url, options = {}) {
        //加载倾斜摄影图像
        const defaultOptions = {
            maximumMemoryUsage: 100,
            maximumScreenSpaceError: 32,
            maximumNumberOfLoadedTiles: 1000,
            shadows: false,
            skipLevelOfDetail: true,
            baseScreenSpaceError: 1024,
            skipScreenSpaceErrorFactor: 16,
            skipLevels: 1,
            immediatelyLoadDesiredLevelOfDetail: false,
            loadSiblings: false,
            cullWithChildrenBounds: true,
            dynamicScreenSpaceError: true,
            dynamicScreenSpaceErrorDensity: 0.00278,
            dynamicScreenSpaceErrorFactor: 4.0,
            dynamicScreenSpaceErrorHeightFalloff: 0.25
        }

        const mergedOptions = { ...defaultOptions, ...options, url }
        const tileSet = new Cesium.Cesium3DTileset(mergedOptions)
        this.viewer.scene.primitives.add(tileSet)
        return tileSet
    }


    /**
     * 添加模型到地面的黄色辅助线
     * @param {Cesium.Cartesian3} position - 模型位置
     */
    addGroundLine(callback) {
        this.viewer.entities.add({
            polyline: {
                positions: new Cesium.CallbackProperty(() => {
                    let position = callback()
                    if (!position) return [];
                    let cartographic = Cesium.Cartographic.fromCartesian(position);
                    let groundPosition = Cesium.Cartesian3.fromRadians(
                        cartographic.longitude,
                        cartographic.latitude,
                        0
                    );
                    return [position, groundPosition];
                }, false),
                width: 3,
                material: Cesium.Color.YELLOW,
                clampToGround: false,
                show: true
            }
        });
    };

    /**
     * 全屏开关
     */
    changeFullScreen() {
        if (
            !document.fullscreenElement && // alternative standard method
            !document.mozFullScreenElement &&
            !document.webkitFullscreenElement &&
            !document.msFullscreenElement
        ) {
            // current working methods
            if (this.viewer.container.requestFullscreen) {
                this.viewer.container.requestFullscreen()
            } else if (this.viewer.container.msRequestFullscreen) {
                this.viewer.container.msRequestFullscreen()
            } else if (this.viewer.container.mozRequestFullScreen) {
                viewer.container.mozRequestFullScreen()
            } else if (this.viewer.container.webkitRequestFullscreen) {
                this.viewer.container.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT)
            }
        } else {
            if (document.exitFullscreen) {
                document.exitFullscreen()
            } else if (document.msExitFullscreen) {
                document.msExitFullscreen()
            } else if (document.mozCancelFullScreen) {
                document.mozCancelFullScreen()
            } else if (document.webkitExitFullscreen) {
                document.webkitExitFullscreen()
            }
        }
    }
    // div的全屏显示
    divFullScreen(divId) {
        const fullscreenDiv = document.getElementById(divId);
        if (!document.fullscreenElement && !document.webkitFullscreenElement && !document.mozFullScreenElement && !document.msFullscreenElement) {

            if (fullscreenDiv.requestFullscreen) {
                fullscreenDiv.requestFullscreen();
            } else if (fullscreenDiv.webkitRequestFullscreen) {
                fullscreenDiv.webkitRequestFullscreen();
            } else if (fullscreenDiv.mozRequestFullScreen) {
                fullscreenDiv.mozRequestFullScreen();
            } else if (fullscreenDiv.msRequestFullscreen) {
                fullscreenDiv.msRequestFullscreen();
            }
        } else {
            if (document.exitFullscreen) {
                document.exitFullscreen()
            } else if (document.msExitFullscreen) {
                document.msExitFullscreen()
            } else if (document.mozCancelFullScreen) {
                document.mozCancelFullScreen()
            } else if (document.webkitExitFullscreen) {
                document.webkitExitFullscreen()
            }
        }
    }
    /**
     * 监听鼠标移动，事件回调用于在地图上显示经纬度
     * @param {*} callback 
     */
    moveDegress(callback) {
        const viewer = this.viewer
        const canvas = viewer.scene.canvas
        const ellipsoid = viewer.scene.globe.ellipsoid
        const handler = new Cesium.ScreenSpaceEventHandler(canvas)
        handler.setInputAction((movement) => {
            // 获取鼠标位置的坐标
            const cartesian = viewer.camera.pickEllipsoid(movement.endPosition, ellipsoid)
            if (cartesian) {
                const cartographic = viewer.scene.globe.ellipsoid.cartesianToCartographic(cartesian) //将地图坐标（弧度）转为十进制的度数
                const lat_String = Cesium.Math.toDegrees(cartographic.latitude).toFixed(4) // 纬
                const long_String = Cesium.Math.toDegrees(cartographic.longitude).toFixed(4) //经
                const alti_String = (viewer.camera.positionCartographic.height / 1000).toFixed(2) //高
                callback({ lat: lat_String, long: long_String, alti: alti_String })
            } else {
                callback()
            }

            // 获取鼠标位置的实体
            const pickedObject = viewer.scene.pick(movement.endPosition);
            let entity = pickedObject?.id;
            // 重置当前选中实体的样式
            const resetEntityStyle = (entity) => {
                if (!entity) return;
                entity.billboard.scale = 0.15;
                entity.billboard.color = Cesium.Color.WHITE;
                entity.label.fillColor = Cesium.Color.fromCssColorString("#0bf7fc");
            };

            // 如果鼠标悬停在实体上，设置高亮样式
            if (Cesium.defined(pickedObject) && entity instanceof Cesium.Entity && entity.info != null) {
                resetEntityStyle(this.selectedEntity);
                entity.billboard.scale = 0.2;
                entity.billboard.color = Cesium.Color.YELLOW;
                entity.label.fillColor = Cesium.Color.YELLOW;
                this.selectedEntity = entity;
            } else {
                resetEntityStyle(this.selectedEntity);
            }

        }, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
    }


    /**
     * 监听鼠标双击事件，如果是实体，则视角移动到实体
     */
    addDoubleClickEvent() {
        const camera = this.viewer.camera
        this.viewer.screenSpaceEventHandler.setInputAction((click) => {
            const pickedObject = this.viewer.scene.pick(click.position);
            if (Cesium.defined(pickedObject) && pickedObject.id instanceof Cesium.Entity && pickedObject.id.info != null) {
                this.selectedEntity = pickedObject.id;
                let height = camera.positionCartographic.height;
                if (height != this.pointHeight) {
                    camera.flyTo({
                        destination: Cesium.Cartesian3.fromDegrees(Number(this.selectedEntity.info.longitude), Number(this.selectedEntity.info.latitude), this.pointHeight),
                    })
                }
            }
        }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
    }

    /**
     * 监听鼠标单击事件，事件回调用于如果是实体，则返回屏幕坐标位置以及实体
     * @param {*} callback 
     */
    addClickEvent(callback) {
        // console.log("this.viewer", this.viewer)
        this.viewer.screenSpaceEventHandler.setInputAction((click) => {
            const pickedObject = this.viewer.scene.pick(click.position);
            if (Cesium.defined(pickedObject) && pickedObject.id instanceof Cesium.Entity && pickedObject.id.info != null) {
                this.selectedEntity = pickedObject.id;
                this.position = this.getPosition(this.selectedEntity);
                this.flag = true;
                callback(this.selectedEntity, this.position, this.flag)
            } else {
                this.selectedEntity = null;
                this.flag = false;
                // 将屏幕坐标转换为椭球体表面的地理坐标
                const cartesian = this.viewer.camera.pickEllipsoid(click.position, this.viewer.scene.globe.ellipsoid);
                if (cartesian) {
                    // 转换为经纬度（弧度）
                    const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
                    // 转换为度
                    const longitude = Cesium.Math.toDegrees(cartographic.longitude);
                    const latitude = Cesium.Math.toDegrees(cartographic.latitude);
                    const height = cartographic.height; // 椭球体表面高度（非地形高度）
                    callback(this.selectedEntity, { longitude, latitude, height }, this.flag)
                }
            }
        }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    }

    /**
     * 监听渲染后事件，事件回调用于实时获取实体所在屏幕坐标位置
     * @param {*} callback 
     */
    addPostRenderEvent(callback) {
        this.viewer.scene.postRender.addEventListener(() => {
            if (this.flag && this.selectedEntity) {
                this.position = this.getPosition(this.selectedEntity);
                // 3D模式
                this.isBehind = this.isEntityBehindEarth(this.selectedEntity)
                if (this.isBehind) {
                    this.flag = false
                    this.selectedEntity = null
                }
                callback(this.position, this.isBehind)
            }
        });
    }

    /**
     * 3D模式检查Entity是否在地球的背面  
     */
    isEntityBehindEarth(entity) {
        let visible = null;
        // 判断是否3D模式
        if (this.viewer.scene.mode === Cesium.SceneMode.SCENE3D) {
            const ellipsoid = Cesium.Ellipsoid.WGS84
            const camera = this.viewer.camera
            // 获取当前时钟时间下实体的位置
            const point = entity.position.getValue(this.viewer.clock.currentTime)
            const occluder = new Cesium.EllipsoidalOccluder(ellipsoid, camera.position)
            visible = occluder.isPointVisible(point)
        } else {
            // 其他模式都是可见
            visible = true
        }
        return !visible

    }

    // 获取实体在画布上的位置  
    getPosition(selectedEntity) {
        const cesiumPosition = selectedEntity.position.getValue(this.viewer.clock.currentTime);
        const canvasPosition = Cesium.SceneTransforms.wgs84ToWindowCoordinates(this.viewer.scene, cesiumPosition);
        return Cesium.defined(canvasPosition) && { x: canvasPosition.x, y: canvasPosition.y };
    }


    /**
     * 添加实体
     * @param {*} point 
     */
    addEntity(point, type) {
        const entity = new Cesium.Entity({
            id: type + point.name,
            info: point,
            position: Cesium.Cartesian3.fromDegrees(Number(point.longitude), Number(point.latitude)),
            billboard: {
                image: point.imgUrl, // 自定义图标的 URL
                scale: 0.15, // 图标缩放比例
                heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
            },
            label: new Cesium.LabelGraphics({
                text: point.name,
                font: "15px sans-serif",
                fillColor: Cesium.Color.fromCssColorString("#0bf7fc"),
                backgroundColor: Cesium.Color.BLUE.withAlpha(0),
                outlineColor: Cesium.Color.BLACK,
                outlineWidth: 2,
                style: Cesium.LabelStyle.FILL_AND_OUTLINE,
                pixelOffset: new Cesium.Cartesian2(0, 35),
                heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
            })
        })
        this.viewer.entities.add(entity)
    }

    /**
     * 飞到点位
     */
    flyToEntity(id, callback) {
        const camera = this.viewer.camera
        const pointEntity = this.viewer.entities.getById(id)
        if (!pointEntity) return
        camera.flyTo({
            destination: Cesium.Cartesian3.fromDegrees(Number(pointEntity.info.longitude), Number(pointEntity.info.latitude), this.pointHeight),
            complete: () => {
                this.selectedEntity = pointEntity
                this.flag = true
                callback(pointEntity)
            }
        })
    }

    /**
     * 销毁地球
     */
    destroy() {
        this.viewer.destroy()
        this.viewer = null
    }

    /**
     * 开始测量
     * @param {string} type - 测量类型：'distance'(距离) | 'area'(面积) | 'height'(高程)
     */
    startMeasure(type) {
        if (!this.measureTools) {
            this.measureTools = new MeasureTools(this.viewer);
        }
        this.measureTools.start(type);
    }

    /**
     * 清除测量
     */
    clearMeasure() {
        if (this.measureTools) {
            this.measureTools.clear();
        }
    }

    /**
     * 开始标注
     * @param {string} type - 标注类型：'point'(点) | 'line'(线) | 'polygon'(多边形)
     */
    startMark(type) {
        if (!this.markTools) {
            this.markTools = new MarkTools(this.viewer);
        }
        this.markTools.start(type);
    }
}

export default function (documentId) {
    const cesiumUtils = new CesiumUtils(documentId);
    return cesiumUtils;
}